/*
 * $Id: string_ctype.c,v 1.3 2005-09-17 11:30:51 bacon Exp $
 */

#if defined(__MSTRING)
#include <xp/bas/mstring.h>
#elif defined(__WSTRING)
#include <xp/bas/wstring.h>
#else
#include <xp/bas/string.h>
#endif
#include <xp/bas/ctype.h>
#include <xp/bas/memory.h>

xp_bool_t xp_stristype (
	const xp_char_t* str, xp_bool_t(*ctype_func)(xp_cint_t c))
{
	while (*str != XP_CHAR('\0')) {
		if (!ctype_func(*str)) return xp_false;
		str++;
	}
	return xp_true;
}

xp_bool_t xp_strxistype (
	const xp_char_t* str, xp_size_t len, xp_bool_t(*ctype_func)(xp_cint_t c))
{
	const xp_char_t* end = str + len;
	while (str < end) {
		if (!ctype_func(*str)) return xp_false;
		str++;
	}
	return xp_true;
}

xp_size_t xp_strupr (xp_char_t* str)
{
	xp_char_t* p = str;
	while (*p != XP_CHAR('\0')) {
		*p = xp_toupper (*p);
		p++;
	}
	return p - str;
}

xp_size_t xp_strxupr (xp_char_t* str, xp_size_t len)
{
	xp_char_t* end = str + len;
	while (str < end) {
		*str = xp_toupper (*str);
		str++;
	}
	return len;
}

xp_size_t xp_strlwr (xp_char_t* str)
{
	xp_char_t* p = str;
	while (*p != XP_CHAR('\0')) {
		*p = xp_tolower (*p);
		p++;
	}
	return p - str;
}

xp_size_t xp_strxlwr (xp_char_t* str, xp_size_t len)
{
	xp_char_t* end = str + len;
	while (str < end) {
		*str = xp_tolower (*str);
		str++;
	}
	return len;
}

xp_size_t xp_strtrm (xp_char_t* str)
{
	xp_char_t* p = str;
	xp_char_t* s = XP_NULL, * e = XP_NULL;

	while (*p != XP_CHAR('\0')) {
		if (!xp_isspace(*p)) {
			if (s == XP_NULL) s = p;
			e = p;
		}
		p++;
	}

	if (e != XP_NULL) {
		e[1] = XP_CHAR('\0');
		xp_memcpy (str, s, (e - s + 2) * xp_sizeof(xp_char_t));
		return e - s + 1;
	}

	str[0] = XP_CHAR('\0');
	return 0;
}

xp_size_t xp_strxtrm (xp_char_t* str, xp_size_t len)
{
	xp_char_t* p = str, * end = str + len;
	xp_char_t* s = XP_NULL, * e = XP_NULL;

	while (p < end) {
		if (!xp_isspace(*p)) {
			if (s == XP_NULL) s = p;
			e = p;
		}
		p++;
	}

	if (e != XP_NULL) {
		/* do not insert a terminating null */
		/*e[1] = XP_CHAR('\0');*/
		xp_memcpy (str, s, (e - s + 2) * xp_sizeof(xp_char_t));
		return e - s + 1;
	}

	/* do not insert a terminating null */
	/*str[0] = XP_CHAR('\0');*/
	return 0;
}

xp_size_t xp_strpac (xp_char_t* str)
{
	xp_char_t* p = str, * q = str;

	while (xp_isspace(*p)) p++;
	while (*p != XP_CHAR('\0')) {
		if (xp_isspace(*p)) {
			*q++ = *p++;
			while (xp_isspace(*p)) p++;
		}
		else *q++ = *p++;
	}

	if (q > str && xp_isspace(q[-1])) q--;
	*q = XP_CHAR('\0');

	return q - str;
}

xp_size_t xp_strxpac (xp_char_t* str, xp_size_t len)
{
	xp_char_t* p = str, * q = str, * end = str + len;
	xp_bool_t followed_by_space = xp_false;
	int state = 0;

	while (p < end) {
		if (state == 0) {
			if (!xp_isspace(*p)) {
				*q++ = *p;
				state = 1;
			}
		}
		else if (state == 1) {
			if (xp_isspace(*p)) {
				if (!followed_by_space) {
					followed_by_space = xp_true;
					*q++ = *p;
				}
			}
			else {
				followed_by_space = xp_false;
				*q++ = *p;	
			}
		}

		p++;
	}

	return (followed_by_space) ? (q - str -1): (q - str);
}
